#include "Balloon.h"
#include "Human.h"
#include "SharedConstants.h"
#include "World.h"

#include <cmath>

Balloon::Balloon(World &i_world,
                 EBalloonColor i_balloon_color,
                 TVector3 i_shift,
                 const Human* ip_human,
                 size_t i_number_of_frames)
  : m_world(i_world)
  , m_shift(i_shift)
  , mp_human(ip_human)
  , m_state(0)
  , m_color(i_balloon_color)
  , m_number_of_frames(i_number_of_frames)
  {
  switch (i_balloon_color)
    {
    case EBalloonColor::BC_BLUE:
      m_str_color = "BLUE";
      break;
    case EBalloonColor::BC_YELLOW:
      m_str_color = "YELLOW";
      break;
    default:
      break;
    }
  m_position = GetPosition();
  m_name = m_str_color + "_BALLOON " + std::to_string(m_id_cnt++);

  m_world.AddRenderable(this);
  m_world.AddAnimated(this);
  m_world.AddMovable(this);
  }

double Balloon::GetAngleAroundY() const 
  {
  if (mp_human != nullptr)
    return mp_human->GetAngleAroundY();
  return 0.0;
  }

void Balloon::NextFrame()
  {
  m_state = (m_state + 1) % m_number_of_frames;
  }

void Balloon::Move()
  {
  }

TVector3 Balloon::GetPosition() const
  {
  TVector3 position = m_shift;
  if (mp_human != nullptr)
    {
    double rotate_mat[2][2] = {{cos(mp_human->GetAngleAroundY() / 180.0 * acos(-1.0)), sin(mp_human->GetAngleAroundY() / 180.0 * acos(-1.0))},
                               {-sin(mp_human->GetAngleAroundY() / 180.0 * acos(-1.0)), cos(mp_human->GetAngleAroundY() / 180.0 * acos(-1.0))}};
    position = TVector3(m_shift[0] * rotate_mat[0][0] + m_shift[1] * rotate_mat[0][1],
                        m_shift[0] * rotate_mat[1][0] + m_shift[1] * rotate_mat[1][1],
                        m_shift[2]);
    position += mp_human->GetPosition();
    }
  return position;
  }

std::string Balloon::GetName() const
	{
	return m_name;
	}

std::string Balloon::GetType() const
  {
  return m_str_color + "_BALLOON_" + std::to_string(m_state);
  }

EBalloonColor Balloon::GetColor() const
  {
  return m_color;
  }

Balloon::~Balloon()
  {
  m_world.RemoveAnimated(this);
  m_world.RemoveRenderable(this);
  m_world.RemoveMovable(this);
  }